// tcp handling

#include "tcp.h"
#include "eth.h"
#include "ip.h"

// last sequence number
unsigned int lastSeq = 1;

// handles a tcp packet
void handleTCPpacket(ethernet_t *eth, packet_t *p)
{
	// get a ip header too
	ipHeader_t* ip = (ipHeader_t*) ethernetStripHeader( p );
	
	// tell me
	printf( "Recevied TCP packet from %d.%d.%d.%d\n", IPAddr0( ip->ipSrc ), IPAddr1( ip->ipSrc ), IPAddr2( ip->ipSrc ), IPAddr3( ip->ipSrc ) );
	
	// strip the headers
	tcpPacket* myPack = (tcpPacket*) ipStripHeader( p );
	
	/** print the tcp packet header **/	
	printf( "Received TCP packet (total size is %d):\n", p->len );
	printf( "Source port: %d\n", ntohs( myPack->sourcePort ) );
	printf( "Destination port: %d\n", ntohs( myPack->destPort ) );
	printf( "Sequence number: %d\n", ntohl( myPack->seqNum ) );
	printf( "Acknowledgment number: %d\n", ntohl( myPack->ackNum ) );
	printf( "Data offset: %d\n", myPack->dataOffset );
	printf( "Reserved: %d\n", myPack->reserved );
	printf( "Flags\n" );
		printf( "\tCWR: %d\n", myPack->packFlags.CWR );
		printf( "\tECE: %d\n", myPack->packFlags.ECE );
		printf( "\tURG: %d\n", myPack->packFlags.URG );
		printf( "\tACK: %d\n", myPack->packFlags.ACK );
		printf( "\tPSH: %d\n", myPack->packFlags.PSH );
		printf( "\tRST: %d\n", myPack->packFlags.RST );
		printf( "\tSYN: %d\n", myPack->packFlags.SYN );
		printf( "\tFIN: %d\n", myPack->packFlags.FIN );
	printf( "Window size: %d\n", ntohs( myPack->WindowSize ) );
	printf( "Checksum: %d\n", ntohs( myPack->Checksum ) );
	printf( "Urgent pointer: %d\n", ntohs( myPack->UrgPtr) );
	
	// check for sync
	if( myPack->packFlags.SYN == 1 )
	{
		// acknowledge
		
		// length of ack packet
		int acklen = ntohs( ip->len ) - sizeof( ipHeader_t );
		
		// data for it
		char* dat = (char*) kmalloc( acklen );
		
		// copt the old data
		memcpy( dat, (char*) myPack, acklen );
		
		// create the packet
		packet_t* ackpack = packetCreate( dat, acklen );
		
		// get the header
		tcpPacket* ack = (tcpPacket*) ackpack->data;
		
		// fill the header
		ack->sourcePort = myPack->destPort;
		ack->destPort = myPack->sourcePort;
		ack->seqNum = myPack->seqNum;
		ack->ackNum = htonl( ntohl( myPack->seqNum ) + 1 );
		ack->Checksum = 0;
		ack->packFlags.ECE = 0;
		ack->packFlags.ACK = 1;
		ack->packFlags.SYN = 1;
		ack->Checksum = packetChecksum( ackpack, acklen );
		
		// send the packet
		ipSendPacket( eth, ip->ipSrc, ackpack, IP_TYPE_TCP, 0 );
	}
	else
	{
		// print the data
		printf( "Data: %s\n", myPack->packData );
	}
	
	// set the acknowledgment number
	myPack->ackNum = myPack->seqNum;
	
	// increment the sequence number
	myPack->seqNum = lastSeq++;
	
	// clear the ECE flag
	myPack->packFlags.ECE = 0;
	
	// print the data
	//kprintf( "%s\n", myPack->packData );
	
	// check if the 'ack' bit is set
/*	if( myPack->packFlags.ACK )
	{
		// acknowledgement, data coming
	}
	else if( myPack->packFlags.SYN )
	{
		// sync
	}
	else
	{
		// print the data
		kprintf( "%s\n", myPack->packData );
	}*/
	
	// ...
	// ipSendPacket(eth, ip->ipSrc, p, IP_TYPE_TCP);
}
